home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Development Platforms / HyperCard Related / XCMDs & XFCNs / Scan / scan.c < prev   
Encoding:
C/C++ Source or Header  |  1990-10-01  |  20.5 KB  |  604 lines  |  [TEXT/MPS ]

  1. /**
  2. ***
  3. **            Module: SCAN
  4. **            Neil M. Day
  5. **            August 9, 1990
  6. **            Apple Computer, Inc. 
  7. **
  8. **            An XCMD to collect information on all files on a specified volume.
  9. **
  10. **            Calling Form: scan (VolumeName,OutputFileName,[output format])
  11. **                where         VolunmeName is then name of the volume to scan (ex. "Nerd Magnet:")
  12. **                            OutputFileName is the full pathname to the output file
  13. **                            [output format] is the optional output string which may include
  14. **                                    F   filename
  15. **                                    C   creator
  16. **                                    T    type
  17. **                                    S   size 
  18. **                                    P   the pathname to the file
  19. **
  20. **            If the output format is not specified it assumes all fields.
  21. **            Too few or too many arguments gives you the calling format.
  22. **
  23. **            Uses the recursive PBGetCatInfo algorithm described in TN68 to step through
  24. **            the volume.
  25. **
  26. **                                        This is version 2.0
  27. **
  28. **            I would like to extend my most sincere thanks to Jeremy Bornstien, Paul Snively,
  29. **            James Benninghaus and others in DTS without whom this wouldn't have been possible.
  30. **
  31. **            Use the following MPW commands to link this
  32. **
  33. **                c -b scan.c
  34. **                link -w -rt XFCN=22501 ∂
  35. **                    -m ENTRYPOINT∂
  36. **                    -sg scan scan.c.o∂
  37. **                    "{libraries}HyperXLib.o" ∂
  38. **                    "{libraries}Interface.o" ∂
  39. **                    "{Clibraries}"StdCLib.o ∂
  40. **                    "{Clibraries}"CInterface.o ∂
  41. **                    "{Clibraries}"CRuntime.o ∂
  42. **                    -o "Scan Demo Stack"
  43. **
  44. ***
  45. **/
  46.  
  47. #include <types.h>                                                        /* Compiler Interfaces to */
  48. #include <resources.h>                                                    /* various managers and   */
  49. #include <files.h>                                                        /* resources ...          */
  50. #include <Packages.h>
  51. #include <String.h>
  52. #include <OSEvents.h>
  53. #include <Memory.h>
  54. #include <Events.h>
  55. #include <Errors.h>
  56. #include <Desk.h>
  57. #include <Strings.h>
  58. #include <Memory.h>
  59. #include <OSUtils.h>
  60. #include <HyperXCmd.h>
  61.  
  62. #define BUFFSIZE    522                                                    /* Size of our IO buffer  */
  63. #define NULL        0
  64.  
  65. #define NEWFILE_CANCELED -1;                                            /* cancel and error codes */
  66.  
  67. OSErr NewFile (char *FileName,char *buffer,HParmBlkPtr paramBlock);        /* Function Prototypes    */
  68. OSErr WriteData (long nBytes,HParmBlkPtr paramBlock);
  69. OSErr CloseFile (HParmBlkPtr paramBlock);
  70. void SCopy (unsigned short pos,char *dest,char *source);
  71. Boolean CheckCancel (void);
  72. void scan (long searchDir);
  73. char *pStrcat (unsigned char *s,unsigned char *t);
  74. char *pStrcpy (unsigned char *s,unsigned char *t);
  75. char *pathName(long dirID,short vRefNum,char *s);
  76. char *nameRecover (unsigned long l,unsigned char *s);
  77. void h2pstr (char *dest,Handle source);
  78. void h2cstr (char *dest,Handle source);
  79. Handle str2h (char *str);
  80. short gimmieVRefNum (const char *name);
  81.  
  82. CInfoPBRec gBlock;                                                        /* Global variables       */
  83. HParamBlockRec it;
  84. char gName[255];
  85. char outputStr[30];                                                        
  86. Boolean deadandgone;
  87.  
  88. typedef    Handle A5RefType;                                                /* A5 world management    */
  89. volatile long gHostA5;                                                    /* stuff goes here        */
  90.  
  91. extern void    A5Init (Ptr myA5);
  92. extern long    A5Size (void);
  93. OSErr makeA5World (A5RefType *A5Ref);
  94. long setA5World (A5RefType A5Ref);
  95. void restoreA5World    (long oldA5, A5RefType A5Ref);
  96. void disposeA5World    (A5RefType A5Ref);
  97.  
  98. pascal void EntryPoint (XCmdPtr paramPtr)
  99. {
  100.     short target_vRefNum;                                    /* vRefNum for the volume to be scaned*/
  101.     Boolean oktofree = true;                                /* Only if the newHandle was succesful*/
  102.     char fname[512];                                        /* container for outPut fileName      */
  103.     Handle Error;                                            /* Error message to return....          */
  104.     A5RefType A5Ref;                                        /* container for new A5 global section*/
  105.     char *buffer;                                            /* A buffer for various stuff         */
  106.     OSErr res;                                                /* a place for my errors              */
  107.     
  108.     res = makeA5World (&A5Ref);                                /* create new A5 world                */
  109.     if (res) {                                                /* if there was a problem...          */
  110.         Error = str2h ("SCAN: Ran out of memory (A5 World)");    /* report the problem              */
  111.         oktofree = false;                                    /* don'd deallocate a bad handle      */
  112.         deadandgone = true;                                    /* set the "Nuked Flag"                  */
  113.         goto EXITPOINT;                                        /* leave      (AAAHHHRRRGGG!!!)       */
  114.     }
  115.     gHostA5 = setA5World (A5Ref);                            /* change to new world; save old one  */
  116.     
  117.     deadandgone = false;                                    /* keep it alive, bro                 */
  118.     
  119.     buffer = NewPtrClear(BUFFSIZE);                            /* Allocate space for the buffer      */
  120.     if (buffer == memFullErr) {                                /* if an anomoly in allocation occured*/
  121.         Error = str2h ("SCAN: Ran out of memory (buffer)"); /*load appropriate error message      */
  122.         deadandgone = true;                                    /* announce a death in the family     */
  123.         goto EXITPOINT;                                        /* leave   (the pain is INTOLERABLE)  */
  124.     }
  125.     switch (paramPtr->paramCount) {
  126.         case 2 :
  127.             h2pstr (buffer,paramPtr->params[0]);            /* copy volume name into the buffer   */
  128.             h2pstr (fname,paramPtr->params[1]);                /* copy output file name into fname   */
  129.             SCopy (0,outputStr,"FCTSP\0");                    /* default output format              */
  130.             break;
  131.         case 3 :
  132.             h2pstr (buffer,paramPtr->params[0]);            /* copy volume name into the buffer   */
  133.             h2pstr (fname,paramPtr->params[1]);                /* copy output file name into fname   */
  134.             h2cstr (outputStr,paramPtr->params[2]);            /* copy formatting info into its home */
  135.             break;
  136.         default :
  137.             deadandgone = true;                                /* kill it                            */
  138.             Error = str2h ("scan (VolumeName,OutputFile[,CMDStr])");
  139.             goto EXITPOINT;
  140.             break;
  141.     }
  142.  
  143.  
  144.     target_vRefNum = gimmieVRefNum (buffer);                /* get the vRefNum from name string   */
  145.  
  146.     if (target_vRefNum == nsvErr) {                            /* if there is no such volume...      */
  147.         Error = str2h ("SCAN: Couldn't find specified volume");  /* Yet another error message     */
  148.         deadandgone = true;                                    /* death                              */
  149.         goto EXITPOINT;                                        /* leave  (I'm meeelllllttttiiinnngg) */
  150.     }
  151.  
  152.     SCopy (0,buffer,"\0");                                    /* make sure the buffer looks empty   */
  153.     
  154.     res = NewFile (fname,buffer,&it);                        /* Create and open the write file     */
  155.     if (res) {                                                /* if NewFile croaked                 */
  156.         Error = str2h ("SCAN: Couldn't create output file");    /* Moan and complain in an        */
  157.         deadandgone = true;                                        /* established stylee...          */
  158.         goto EXITPOINT;
  159.     }
  160.  
  161.     gBlock.hfileInfo.ioNamePtr = gName;                        /* Set up global Paramater Block for  */
  162.     gBlock.hfileInfo.ioVRefNum = target_vRefNum;            /* various File Manager calls...      */
  163.  
  164.     scan (fsRtDirID);                                        /* look at the whole volume           */
  165.     if (deadandgone) 
  166.         Error = str2h ("SCAN: Canceled");                    /* if we died durring the scan...     */
  167.  
  168.     res = CloseFile (&it);                                     /* Now that we're all done, close it  */
  169.     
  170.     if (res) {                                                /* if we generated an error somewere  */
  171.         Error = str2h ("SCAN: ACK!!!");                        /* put up an informative error message*/
  172.         deadandgone = true;
  173.     }
  174.  
  175. EXITPOINT:
  176.  
  177.     if (buffer != memFullErr) DisposPtr (buffer);            /* free the buffer   (if allocated..) */
  178.  
  179.     if (deadandgone)
  180.         paramPtr->returnValue = Error;                        /* set up the error return...          */
  181.         
  182.     restoreA5World ( gHostA5, A5Ref );                        /* nuke my A5 world and restore that  */
  183.     if (oktofree) disposeA5World ( A5Ref );                    /*  That of Hypercard                 */
  184.     return;
  185. }
  186.  
  187. /*
  188. **        NewFile (char *name,char *buffer,HParmBlkPtr paramBlock)
  189. **            • Creates a new file called 'name' in the current directory.  Returns the
  190. **               Apropriate set of errors...
  191. **            • Be forewarned that NewFile is completely destructive to paramBlock.
  192. **            • After the call to NewFile, paramBlock contains the pointer to the opened and
  193. **               created file....
  194. */
  195. OSErr NewFile (FileName,buffer,paramBlock)
  196. char *FileName;
  197. char *buffer;
  198. HParmBlkPtr paramBlock;
  199. {
  200.     OSErr result;                                            /* result of file system calls        */
  201.     
  202.     paramBlock->fileParam.ioNamePtr = FileName;                /* copy filename into Paramater block */
  203.     paramBlock->fileParam.ioVRefNum = NULL;                    /* Full pathname - unneccisary          */
  204.     paramBlock->fileParam.ioDirID =    NULL;                    /* Full pathname - unneccisary..       */
  205.     paramBlock->fileParam.ioCompletion = NULL;                /* No completion routine defined      */
  206.         
  207.     result = PBHCreate (paramBlock,false);                    /* create the file                    */
  208.     if (result != noErr)                                     /* Balk at an error                   */
  209.             return result;
  210.             
  211.     result = PBHGetFInfo (paramBlock,false);                /* Get the existant info on file      */    
  212.     if (result != noErr)                                    /* Balk at an error                   */
  213.             return result;
  214.             
  215.     paramBlock->fileParam.ioNamePtr = FileName;                /* copy filename into Paramater block */
  216.  
  217.     paramBlock->fileParam.ioCompletion = NULL;                /* No completion routine defined      */
  218.     paramBlock->fileParam.ioFlFndrInfo.fdType =                /* ZAP!! Make it a text file          */
  219.             (OSType)'TEXT';
  220.     paramBlock->fileParam.ioFlFndrInfo.fdCreator =             /* ZAP!! Make it MY text file         */    
  221.             (OSType)'CAML';    
  222.     paramBlock->fileParam.ioFlVersNum = 0;                    /* make sure the version is 0         */
  223.     result = PBHSetFInfo (paramBlock,false);                /* Update the Information             */
  224.     if (result != noErr)                                    /* Balk at an error                   */
  225.             return result;
  226.  
  227.     paramBlock->ioParam.ioMisc = buffer;                    /* tell read where me buffer be       */
  228.     paramBlock->ioParam.ioBuffer = buffer;                    /* tell read where me buffer be       */
  229.     paramBlock->ioParam.ioPermssn = fsWrPerm;                /* Set the file up for writin         */
  230.  
  231.     result = PBHOpen (paramBlock,false);                    /* open the file for writin'          */
  232.     if (result != noErr)                                    /* Balk at an error                   */
  233.             return result;
  234.     
  235.     return noErr;                                            /* Sayoonara , NewFile-san            */
  236. }
  237.  
  238. /*
  239. **        WriteData (long nBytes,ParmBlkPtr paramBlock)
  240. **            •Writes nBytes of the buffer defined in the previous call to NewFile to the file
  241. **              opened by NewFile.
  242. **            •Does the appropriate allocations, etc..
  243. */
  244. OSErr WriteData (nBytes,paramBlock)
  245. long nBytes;
  246. HParmBlkPtr paramBlock;
  247. {
  248.     OSErr result;                                            /* result of file system calls        */
  249.         
  250.     paramBlock->ioParam.ioReqCount = nBytes;                /* the number of bytes to allocate    */
  251.  
  252.     result = PBWrite ((ParmBlkPtr)paramBlock,false);        /* Dump that Chump (to disk)          */
  253.     if (result != noErr) return result;                        /* Balk at an error                   */
  254.     
  255.     return noErr;                                            /* Our hero rides off into the sunset */
  256. }    
  257.  
  258. /*
  259. **        CloseFile (ParmBlkPtr paramBlock)
  260. **            • Closes the file and flushes the file and volume. Hooray
  261. */
  262. OSErr CloseFile (paramBlock)
  263. HParmBlkPtr paramBlock;
  264. {
  265.     OSErr result;                                            /* result of file system calls        */
  266.  
  267.     result = PBFlushFile ((ParmBlkPtr)paramBlock,false);    /* give file TY-DI-BOWL treatment     */
  268.     if (result != noErr) {
  269.         Debugger();
  270.         return result;                                        /* Balk at an error                   */
  271.     }
  272.  
  273.     result = PBClose ((ParmBlkPtr)paramBlock,false);        /* Close that puppy                   */
  274.     if (result != noErr) {
  275.         Debugger();
  276.         return result;                                        /* Balk at an error                   */
  277.     }
  278.  
  279.     result = PBFlushVol ((ParmBlkPtr)paramBlock,false);        /* give Vol. TY-DI-BOWL treatment     */
  280.     if (result != noErr) {
  281.         Debugger();
  282.         return result;                                        /* Balk at an error                   */
  283.     }
  284.  
  285.     return noErr;                                            /* O.K kids, time to go home          */
  286.  
  287. /*
  288. **        SCopy(pos,dest,source)
  289. **            Does the 'ol full service string copy thing.  Pos specifies the starting position in the 
  290. **            destination.  Whopppe.
  291. */
  292. void SCopy (pos,dest,source)
  293. unsigned short pos;
  294. char dest[],source[];
  295. {
  296.     unsigned short i=0;                                        /* normal index declaration           */
  297.     
  298.     while (dest[i+pos] = source[i]) i++;                    /* standard string copy routine       */
  299. }
  300.  
  301. /*
  302. **        CheckCancel ()
  303. **            Checks for a command-period event - bealches when one is encountered.
  304. */
  305. Boolean CheckCancel (void)
  306. {
  307.     EventRecord myEvent;
  308.     
  309.     SystemTask ();                                            /* do any pending system operations   */
  310.     
  311.     if (deadandgone) return false;                            /* multiple cancels are not good....  */
  312.     
  313.     if (GetNextEvent(everyEvent^diskMask,&myEvent)) {        /* get all events minus disk events   */
  314.         if (myEvent.what == keyDown) {                        /* if it's a keydown, and ...         */
  315.             SysBeep(1);                                        /* a little audio feedback...          */
  316.             return (myEvent.modifiers & cmdKey) &&             /* a command - "." ?!?!                  */
  317.             ((myEvent.message & charCodeMask) == '.');        /* period then return true            */
  318.         }
  319.     }
  320.     return false;
  321. }
  322.  
  323. /*
  324. **         scan (directory)
  325. **            This routine steps through the volume, and writes data on specific files out to 
  326. **            the file previously opened by NewFile.
  327. **                    • Highly recursive
  328. **                    • Highly simple
  329. **                    • Highly gleaned from DTS sample code
  330. */
  331. void scan (searchDir)
  332. long searchDir;
  333. {
  334.     char string[1024];                                        /* BIG string for pathnames           */
  335.     char type [6];                                            /* little string for type/creator info*/
  336.     char numObytes[256];                                    /* a place for my byte string         */
  337.     long totalsize;                                            /* total Size of the file             */
  338.     Boolean dirFlag = false;                                /*"This is a directory" flag...       */
  339.     Boolean first = true;                                    /* first time through flag...         */
  340.     short index = 1;                                        /* index into the current directory   */
  341.     short cntr;                                                /* your generic counter...              */
  342.     OSErr err;                                                /* container for errors               */
  343.     
  344.     if (deadandgone) return;                                /* sprial up through the recursion    */
  345.     
  346.     do {
  347.         gBlock.hfileInfo.ioFDirIndex = index;                /* set file up file index             */
  348.         gBlock.hfileInfo.ioDirID = searchDir;                /* set the directory to search        */
  349.         
  350.         if (CheckCancel ()) {                                /* exit routine on a CANCEL request   */
  351.             deadandgone = true;                                /* unleash the recursion killer....   */    
  352.             return;
  353.         }
  354.         
  355.         err = PBGetCatInfo (&gBlock,false);                    /* get current file info              */
  356.         
  357.         if (!err) {
  358.             if (first) {                                    /* only need to get the pathname once */
  359.                 strcpy (&string[0],    p2cstr(pathName(dirFlag ? gBlock.hfileInfo.ioDirID : 
  360.                                                               gBlock.hfileInfo.ioFlParID,            
  361.                                         gBlock.hfileInfo.ioVRefNum,        /* Structures make such   */
  362.                                         &string[0])));                    /* nice readable code.... */                
  363.                 first = false;
  364.             }
  365.  
  366.             if ((gBlock.hfileInfo.ioFlAttrib>>4) & 0x01)    /* if the current file is a directory */
  367.                 dirFlag = true;                                /* set the directory flag to true     */
  368.             else
  369.                 dirFlag = false;                            /* set the directory flag to false    */
  370.  
  371.             if (!dirFlag) {                                    /* if it's not a directory            */
  372.                 totalsize = gBlock.hfileInfo.ioFlPyLen + gBlock.hfileInfo.ioFlRPyLen;
  373.                 NumToString(totalsize,numObytes); /* stuff the bytecount to a str*/
  374.                 for (cntr = 0; cntr < strlen (outputStr); cntr++) {
  375.                     switch (outputStr[cntr]) {
  376.                         case 'F':
  377.                             SCopy (0,it.ioParam.ioBuffer,"\"\0");
  378.                             SCopy (strlen (it.ioParam.ioBuffer),it.ioParam.ioBuffer,
  379.                                 p2cstr(gBlock.hfileInfo.ioNamePtr));
  380.                                 SCopy (strlen (it.ioParam.ioBuffer),it.ioParam.ioBuffer, "\" \0");
  381.                             break;
  382.                         case 'C' :
  383.                             SCopy (strlen (it.ioParam.ioBuffer),it.ioParam.ioBuffer,
  384.                                 nameRecover (gBlock.hfileInfo.ioFlFndrInfo.fdCreator,&type[0]));
  385.                             SCopy (strlen (it.ioParam.ioBuffer),it.ioParam.ioBuffer, " \0");
  386.                             break;
  387.                         case 'T' :
  388.                             SCopy (strlen (it.ioParam.ioBuffer),it.ioParam.ioBuffer,
  389.                                 nameRecover (gBlock.hfileInfo.ioFlFndrInfo.fdType,&type[0]));
  390.                             SCopy (strlen (it.ioParam.ioBuffer),it.ioParam.ioBuffer, " \0");
  391.                             break;
  392.                         case 'S' :
  393.                             SCopy (strlen (it.ioParam.ioBuffer),it.ioParam.ioBuffer,
  394.                                 p2cstr(numObytes));
  395.                             SCopy (strlen (it.ioParam.ioBuffer),it.ioParam.ioBuffer, " \0");
  396.                             break;
  397.                         case 'P' :
  398.                             SCopy (strlen (it.ioParam.ioBuffer),it.ioParam.ioBuffer, "\"\0");
  399.                             SCopy (strlen (it.ioParam.ioBuffer),it.ioParam.ioBuffer,
  400.                                 string);
  401.                             SCopy (strlen (it.ioParam.ioBuffer),it.ioParam.ioBuffer, "\"\0");
  402.                             break;
  403.                         default :
  404.                             break;
  405.                     }
  406.                 }
  407.                 SCopy (strlen (it.ioParam.ioBuffer),it.ioParam.ioBuffer, "\n\0");
  408.                 err = WriteData (strlen (it.ioParam.ioBuffer),&it);            /* write the info to disk */
  409.             }
  410.             
  411.             if (dirFlag) scan(gBlock.hfileInfo.ioDirID);    /* recurse with new directory ID */
  412.             ++index;                                        /* incriment the index                */
  413.         }
  414.     } while (!err);                                            /* while there is not an error        */
  415. }                                                            /* end of scan                        */
  416.  
  417. /*
  418. **        pathName (dirID,vRefNum,s)
  419. **            returns a string containing the full pathname to the current file or directory
  420. **            this code is snached from the DTS sample code StdFile.c (but slightly modified).
  421. **            Added support for both files and directories.  NOT A/UX compatable...
  422. */
  423. char *pathName(dirID,vRefNum,s)
  424. long dirID;
  425. short vRefNum;
  426. char *s;
  427. {
  428.     OSErr err;                                                /* error container                    */
  429.     CInfoPBRec block;                                        /* infoBlock to be used CatInfo calls */
  430.     Str255 directoryName;                                    /* a place to stuff my directory name */
  431.     
  432.     *s = 0;
  433.     block.dirInfo.ioNamePtr = &directoryName;
  434.     
  435.     block.dirInfo.ioDrParID = dirID;
  436.     
  437.     do {
  438.         block.dirInfo.ioFDirIndex = -1;                        /* Specify vRefNum and DirID for call */
  439.         block.dirInfo.ioVRefNum = vRefNum;                    /* set the ParamBlock's vRefNum       */
  440.         block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;    /* set the ParamBlock's DirID         */
  441.         
  442.         err = PBGetCatInfo (&block,false);                    /* get information on catalogue       */
  443.         if (err) break;                                        /* get me outta here......            */
  444.         
  445.         pStrcat (&directoryName,"\p:");                        /* add a colon to the begining...     */
  446.         pStrcat (&directoryName,s);                            /* prepose newly found directory name */
  447.         pStrcpy (s,&directoryName);                            /* swap the two                          */
  448.         
  449.     } while (block.dirInfo.ioDrDirID != fsRtDirID);            /* loop till we hit the ceiling (fig) */
  450.     
  451.     return (s);                                                /* cough up the result                  */
  452. }
  453.  
  454. /*
  455. **        pStrcat,pStrcpy
  456. **            two plagarized routines for dealing with pascal strings.  Yea. Hooray. Whoopie
  457. **            DISCLAIMER - I didn't write this stuff, therefore I take no responsibility for the 
  458. *                ease of comprehension of this code.  If you don't understand C well, tough titties.
  459. */
  460. char *pStrcat (s,t)
  461. unsigned char *s, *t;
  462. {
  463.     unsigned char *s2;
  464.     short tLen;
  465.     
  466.     s2 = s + *s;
  467.     *s += (tLen = *t);
  468.     for (++tLen; --tLen; s2[tLen] = t[tLen]);
  469.     return (s);
  470. }
  471.  
  472. char *pStrcpy (s,t)
  473. unsigned char *s, *t;
  474. {
  475.     short tLen;
  476.     
  477.     for (tLen = *t + 1; tLen--; s[tLen] = t[tLen]);
  478.     return (s);
  479. }
  480.  
  481. /*
  482. **        nameRecoer (it,s)
  483. **            returns a ascii string from a long integer (handy when dealing with creator types)
  484. */
  485. char *nameRecover (l,s)
  486. unsigned long l;
  487. unsigned char *s;
  488. {
  489.     short cnt;
  490.     
  491.     for (cnt = 0; cnt < 4; cnt++)
  492.         s[cnt] = (l >> (8*(3-cnt))) & 0xff;                        /* break out bytes & stuff 'em    */
  493.                                                                 /* nice clean little alg, huh...  */
  494.     s[4] = '\0';
  495.     
  496.     return (s);
  497. }
  498.  
  499. /*
  500. **        A5World stuff
  501. **            Ugly Ugly Ugly.
  502. **            Undocumented Undocumented Undocumented.
  503. **            Plagerized Plagerized Plagerized.
  504. */
  505. OSErr makeA5World ( A5RefType *A5Ref )
  506. {
  507.     *A5Ref = NewHandle ( A5Size ( ) );
  508.     if ((*A5Ref == 0) || (MemError() != noErr))                    /* if the allocation crapped out  */
  509.         return memFullErr;                                        /* return the time honored error  */
  510.     HLock ( *A5Ref );
  511.     A5Init ( ( Ptr ) ( * ( *A5Ref ) + A5Size ( ) - 32 ) );
  512.     HUnlock ( *A5Ref );
  513. }
  514.  
  515. long setA5World ( A5RefType A5Ref )
  516. {
  517.     HLock ( A5Ref );
  518.     return ( SetA5 ( ( long ) ( *A5Ref ) + A5Size ( ) - 32 ) );
  519. }
  520.  
  521. void restoreA5World ( long oldA5, A5RefType A5Ref )
  522. {
  523.     if ( SetA5 ( oldA5 ) )
  524.         HUnlock ( A5Ref );
  525. }
  526.  
  527. void disposeA5World ( A5RefType A5Ref )
  528. {
  529.     DisposHandle ( A5Ref );
  530. }
  531.  
  532. /*
  533. **    h2pstr (dest,source)
  534. **        does what it says
  535. **
  536. */
  537. void h2pstr (dest,source)
  538. char *dest;
  539. Handle source;
  540. {
  541.     strcpy ((char *) dest, *source);
  542.     dest = c2pstr (dest);
  543. }
  544.  
  545. /*
  546. **    h2cstr (dest,source)
  547. **        also does what it says
  548. **
  549. */
  550. void h2cstr (dest,source)
  551. char *dest;
  552. Handle source;
  553. {
  554.     strcpy ((char *) dest, *source);
  555. }
  556.  
  557. /*
  558. **    str2h (str)
  559. **        copies a string into a handle and returns it
  560. */
  561.  
  562. Handle str2h (str)
  563. char *str;
  564. {
  565.     Handle new;
  566.     
  567.     new = NewHandleClear ((long) strlen(str) + 1);
  568.     strcpy ((char *) (*new), str);
  569.     
  570.     return (new);
  571. }
  572.  
  573. /*
  574. **        gimmieVRefNum (name)
  575. **            returns a vRefNum from a volume name
  576. */
  577. short gimmieVRefNum (name)
  578. const char *name;
  579. {
  580.     HParamBlockRec sBlock;
  581.     WDPBRec Info;
  582.     OSErr res;
  583.  
  584.     sBlock.fileParam.ioNamePtr = name;                        /* give the pointer some memory       */
  585.     sBlock.fileParam.ioVRefNum = -20;                        /* Way out of range to generate errror*/
  586.     sBlock.volumeParam.ioVolIndex = -1;                        /* set up fileName and VrefNum call   */
  587.     sBlock.fileParam.ioCompletion = NULL;                    /* Vestigial procedure nullification..*/
  588.     
  589.     res = PBHGetVInfo (&sBlock,false);                        /* get volume info                       */
  590.     if (res)                                                 /* if the info call choked, return err*/
  591.         return nsvErr;
  592.  
  593.     Info.ioVRefNum = sBlock.fileParam.ioVRefNum;            /* get the new vol's vrefnum          */
  594.     Info.ioWDIndex = 0;                                        /* get dir info from vRefNum only     */
  595.     Info.ioWDProcID = 0;                                    /* Include info about WDs of all procs*/
  596.  
  597.     res = PBGetWDInfo ( ((WDPBPtr)&Info) ,false);            /* seperate volume and directory info */
  598.     if (res)                                                 /* if the info call choked, return err*/
  599.         return nsvErr;
  600.     
  601.     return (Info.ioWDVRefNum);                                /* If we survived, return the vRefNum */
  602. }
  603.